//
//    Tokaplot
//    https://code.google.com/p/tokaplot/
//
//    License: GPL v3
//    https://code.google.com/p/tokaplot/wiki/License
//
//    This file is part of Tokaplot.
//
//    Tokaplot is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    Tokaplot is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with Tokaplot.  If not, see <http://www.gnu.org/licenses/>
//

package com.tokaplot;

import android.os.Bundle;
import android.app.Dialog;
import android.view.View;
import android.view.MotionEvent;
import android.view.Window;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;

public class DialogColour extends Dialog {
	
	private OnColourChangedListener dListener;	
	private static int dWidth = 1;
	private static int dHeight = 1; 
	private static float dRadius = 1.0f;
	private static float dSpacing = 1.0f;
 	private static final int nColours = 8;
 	private static int vAlpha[];
 	private static int vColours[][];
 	private static int si, sj, sa;
 	private static boolean colourSelected = false;
 	
    public interface OnColourChangedListener {
        void colourChanged(int colour);
    }
    
    public DialogColour(Context context, int colour, OnColourChangedListener listener) {
        super(context);
        
        // Set listener and start colour
        dListener = listener;
        si = 0;
        sj = 0;
        sa = 7;
        
        float screenDensity = context.getResources().getDisplayMetrics().density;
        dWidth = (int)(200*screenDensity + 0.5f);
        dHeight = (int)(200*screenDensity + 0.5f);
        dRadius = 6.0f*screenDensity;
        dSpacing = 10.0f*screenDensity;
        
        vColours = new int[nColours+1][nColours];
        int i,j;
    	for (j=0;j<nColours;j++)
    		for (i=0;i<nColours;i++) {
    			vColours[i][j]=HLStoRGB(360.0f*i/(float)nColours, 0.1f+(j/(float)nColours)*0.9f, 1.0f);
    			if ((vColours[i][j]&0xFFFFFF) == (colour&0xFFFFFF)) {
    				si=i;
    				sj=j;
    			}
    		}
    	
    	int grayScaleVal;
    	for (j=0;j<nColours;j++) {
    		grayScaleVal = j*32 + 31;
    		vColours[nColours][j]=Color.rgb(grayScaleVal, grayScaleVal, grayScaleVal);
			if ((vColours[nColours][j]&0xFFFFFF) == (colour&0xFFFFFF)) {
				si=nColours;
				sj=j;
			}
    	}
    	
        vAlpha = new int[nColours];
        for (j=0;j<nColours;j++) {
        	vAlpha[j] = j*32 + 31;
    		if (vAlpha[j] == ((colour>>0x18)&0xFF)) {
    			sa = j;
    		}
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

		
        // Create listener
        OnColourChangedListener listener = new OnColourChangedListener() {
            public void colourChanged(int colour) {
                dListener.colourChanged(colour);
                dismiss();
            }
        };
        
		requestWindowFeature(Window.FEATURE_LEFT_ICON);
		setContentView(new DialogColourView(getContext(), listener));
		setTitle("Set colour");		
		setFeatureDrawableResource(Window.FEATURE_LEFT_ICON, R.drawable.icon);
    } 
    
    // View class
    private static class DialogColourView extends View {
        private OnColourChangedListener vListener;

        DialogColourView(Context context, OnColourChangedListener listener) {
            super(context);
            vListener = listener;
        }

        @Override 
        protected void onDraw(Canvas canvas) {
        	
        	Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
        	int i,j;
        	
        	float px = 0.0f;
        	float py = 0.0f;
        	float dx = (float)dWidth/(float)(nColours+1);
        	float dy = (float)dHeight/(float)nColours;
        	
			// Draw opacity circles
			p.setStyle(Paint.Style.FILL);
			for (j=0;j<nColours;j++) {
				p.setARGB(vAlpha[j], 128, 128, 128);
				canvas.drawCircle(dWidth + dSpacing, (j + 0.5f)*dy, dRadius*1.1f, p);
			}
			
        	// Draw colour boxes
			p.setStyle(Paint.Style.FILL);			
        	for (j=0;j<nColours;j++) {
        		px = 0.0f;
        		for (i=0;i<nColours+1;i++) {
        			p.setColor(vColours[i][j]);
        			p.setAlpha(vAlpha[sa]);
        			canvas.drawRoundRect(new RectF(px + 2.0f, py + 2.0f, dx + px - 2.0f, dy + py - 2.0f), 5.0f, 5.0f, p);
        			px+=dx;
        		}
        		py+=dy;
        	}
        	
        	// Draw selections
        	p.setColor(0xFFFFFFFF);
        	p.setStyle(Paint.Style.STROKE);
        	p.setStrokeWidth(2.0f);
        	canvas.drawCircle(dWidth + dSpacing, (sa + 0.5f)*dy, dRadius, p);
			canvas.drawRoundRect(new RectF(si*dx + 1.0f, sj*dy + 1.0f, (si + 1)*dx - 1.0f, (sj + 1)*dy - 1.0f), 6.0f, 6.0f, p);
			
        }

        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        	
            setMeasuredDimension(dWidth + (int)(dSpacing*2.0f), dHeight);
        }

        @Override
        public boolean onTouchEvent(MotionEvent event) {

            switch (event.getAction()) {
            
	            case MotionEvent.ACTION_DOWN: {
                	int i = (int) ((nColours+1)*(event.getX()/dWidth));
                	int j = (int) (nColours*(event.getY()/dHeight));
                	if (i<0) i = 0;
                	if (j<0) j = 0;
                	if (j>nColours-1) j = nColours-1;
                	if (i>nColours) {
                		sa = j;
                		colourSelected = false;
                	} else {
	                	si = i;
	                	sj = j;
	                	colourSelected = true;
                	}
                	invalidate();
	            	}
	            	break;
	                    
	            case MotionEvent.ACTION_MOVE: {
                	int i = (int) ((nColours+1)*(event.getX()/dWidth));
                	int j = (int) (nColours*(event.getY()/dHeight));
                	if (i<0) i = 0;
                	if (j<0) j = 0;
                	if (j>nColours-1) j = nColours-1;
                	if (i>nColours) {
                		sa = j;
                		colourSelected = false;
                	} else {
	                	si = i;
	                	sj = j;
	                	colourSelected = true;
                	}
                	invalidate();
	            	}
	            	break;
	            	
                case MotionEvent.ACTION_UP: {
                	if (colourSelected) {
                		int colour = (vColours[si][sj] & 0xFFFFFF) | ((vAlpha[sa] & 0xFF) << 0x18);
                		vListener.colourChanged(colour);
                	}
                	invalidate();
                	}
                	break;
            }
            return true;
        }
        

    }
    
    public int HLStoRGB(float H, float L, float S) {
    	// Convert from Hue (H, 0 - 360 degrees), Luminance (L, 0 - 1) and Saturation (S, 0 - 1) to RGB
    	
    	float r = 0.0f;
    	float g = 0.0f;
    	float b = 0.0f;
    	float w = 0.0f;
    	float chroma = (1.0f-Math.abs(2.0f*L-1.0f))*S;
    	float hue = (float)H/60.0f;
    	float magic = chroma*(1.0f - Math.abs((hue%2.0f)-1.0f));
    	
    	if (hue<0.0f || hue>6.0f) {r = 0.0f; g = 0.0f; b = 0.0f;}
    	else if (hue<1.0f) {r = chroma; g = magic; b = 0.0f;}
    	else if (hue<2.0f) {r = magic; g = chroma; b = 0.0f;}
    	else if (hue<3.0f) {r = 0.0f; g = chroma; b = magic;}
    	else if (hue<4.0f) {r = 0.0f; g = magic; b = chroma;}
    	else if (hue<5.0f) {r = magic; g = 0.0f; b = chroma;}
    	else if (hue<6.0f) {r = chroma; g = 0.0f; b = magic;}
    	
    	w = L - 0.5f*chroma;
    	
    	return Color.rgb((int)(255.0f*(w+r)), (int)(255.0f*(w+g)), (int)(255.0f*(w+b)));
    }
}